<template>
  <div class="drag-verify-container">
    <div class="title">安全验证</div>
    <div class="tips">完成验证后，系统自动下发短信验证码</div>
    <div class="pic-container">
      <img
        :src="
          dragVerifyData.originalImageBase64
            ? 'data:image/png;base64,' + dragVerifyData.originalImageBase64
            : ''
        "
        alt=""
        class="bg"
        ref="bgRef"
        draggable="false"
      />
      <img
        :src="
          dragVerifyData.jigsawImageBase64
            ? 'data:image/png;base64,' + dragVerifyData.jigsawImageBase64
            : ''
        "
        alt=""
        class="blockPuzzle"
        ref="blockPuzzleRef"
        draggable="false"
      />
      <img
        src="@/components/image/drag-verify/refresh@2x.png"
        alt=""
        class="refresh"
        @click="refresh"
        draggable="false"
      />
    </div>
    <div
      class="drag-block-container"
      ref="dragBlockContainerRef"
      v-show="isComplete"
    >
      <div class="drag-block-tips" ref="dragBlockTipsRef">
        <span class="init-tips" v-show="initTipsShow">
          向右滑动滑块完成验证
        </span>
        <div class="success-status" v-show="successTipsShow">
          <img :src="statusIcoUrl.successUrl" alt="" />
          <span>验证成功</span>
        </div>
      </div>
      <div
        class="drag-block"
        ref="dragBlockRef"
        v-show="!successTipsShow"
      ></div>
    </div>
  </div>
</template>

<script>
import { aesEncrypt, sendCaptchaVerification } from "../DragVerify";
import request2 from "@/components/base";
export default {
  data() {
    return {
      isComplete: false,
      appId: 1,
      initTipsShow: true,
      successTipsShow: false,
      canRefresh: true,
      distanceX: 0,
      pointJson: "",
      bgWidth: 0,
      blockPuzzleWidth: 0,
      mouseDownX: 0,
      flag: false,
      dragVerifyData: {},
      captchaVerification: "",
      statusIcoUrl: {
        initUrl: require("@/components/image/drag-verify/drag-clock-1@2x.png"),
        successUrl: require("@/components/image/drag-verify/drag-clock-2@2x.png"),
        failUrl: require("@/components/image/drag-verify/drag-clock-3@2x.png")
      }
    };
  },
  methods: {
    async getCode() {
      const params = {
        captchaType: "blockPuzzle",
        ts: new Date().getTime(),
        appId: this.appId
      };
      const res = await request2.dragVerifyGetCode(params);
      if (res.code !== 0) throw new Error(res.message);
      this.dragVerifyData = res.data;
    },
    async checkCode(pointJson) {
      const params = {
        captchaType: "blockPuzzle",
        pointJson,
        token: this.dragVerifyData.token,
        ts: new Date().getTime(),
        appId: this.appId
      };
      try {
        const res = await request2.dragVerifyCheckCode(params);
        if (res.code !== 0) throw new Error(res.message);
        this.captchaVerification = res.data.captchaVerification;
        setTimeout(() => {
          this.$emit("setdialogType", "phone", {
            captchaVerification: res.data.captchaVerification
          });
        }, 1000);
        return res.data.captchaVerification;
      } catch (e) {
        console.log(e);
      }
    },
    async refresh() {
      if (!this.canRefresh) return;
      this.isComplete = false;
      await this.getCode();
      this.$refs.dragBlockRef.style.left = "0px";
      this.$refs.blockPuzzleRef.style.left = "0px";
      this.$refs.dragBlockContainerRef.style.borderColor = "#13CBB9";
      this.$refs.dragBlockRef.style.backgroundImage = `url(${this.statusIcoUrl.initUrl})`;
      this.initTipsShow = true;
      this.handleJigsawChange();
    },
    getAppId() {
      const ua = window.navigator.userAgent.toLowerCase();
      const index = ua.indexOf("cq_xhl");
      if (index !== -1) {
        const str = ua.slice(index + 7, -1);
        const appId = Number(str.split(";")[2]);
        appId && (this.appId = appId);
      }
    },
    handleJigsawChange() {
      let bgLoaded = false;
      let blockPuzzleLoaded = false;
      this.$refs.bgRef.addEventListener("load", () => {
        this.bgWidth = this.$refs.bgRef.offsetWidth;
        bgLoaded = true;
      });
      this.$refs.blockPuzzleRef.addEventListener("load", () => {
        this.blockPuzzleWidth = this.$refs.blockPuzzleRef.offsetWidth;
        blockPuzzleLoaded = true;
      });
      const timer = setInterval(() => {
        if (bgLoaded && blockPuzzleLoaded) {
          this.isComplete = true;
          clearInterval(timer);

          if (this.$refs.dragBlockContainerRef) {
            this.$refs.dragBlockContainerRef.style.width =
              this.bgWidth -
              this.blockPuzzleWidth +
              parseFloat(window.getComputedStyle(this.$refs.dragBlockRef).width) +
              "px";
          }
          this.bindEvent();
        }
      }, 100);
    },
    touchStart(event) {
      this.mouseDownX = event.clientX || event.touches[0].clientX;

      this.initTipsShow = false;
      this.canRefresh = false;
      this.flag = true;

      window.addEventListener("touchmove", this.touchMove);
      window.addEventListener("touchend", this.touchEnd);
      window.addEventListener("mousemove", this.touchMove);
      window.addEventListener("mouseup", this.touchEnd);
    },
    touchMove(event) {
      if (this.flag) {
        const mouseMoveX = event.clientX || event.touches[0].clientX;
        this.distanceX = mouseMoveX - this.mouseDownX;
        const maxDistanceX = this.bgWidth - this.blockPuzzleWidth;

        if (this.distanceX > maxDistanceX) {
          this.distanceX = maxDistanceX;
        } else if (this.distanceX < 0) {
          this.distanceX = 0;
        }
        this.$refs.dragBlockRef.style.left = this.distanceX + "px";
        this.$refs.blockPuzzleRef.style.left = this.distanceX + "px";
      }
    },
    touchEnd() {
      this.flag = false;
      this.unbindEvent();
      this.pointJson = aesEncrypt(
        JSON.stringify({ x: this.distanceX, y: 5.0 }),
        this.dragVerifyData.secretKey
      );
      this.checkCode(this.pointJson).then((res) => {
        if (res) {
          this.successTipsShow = true;
          sendCaptchaVerification(this.captchaVerification);
        } else {
          this.$refs.dragBlockContainerRef.style.borderColor = "#FF5353";
          this.$refs.dragBlockRef.style.backgroundImage = `url(${this.statusIcoUrl.failUrl})`;
          setTimeout(() => {
            this.canRefresh = true;
            this.refresh();
          }, 2000);
        }
      });
    },
    bindEvent() {
      this.$refs.dragBlockRef.addEventListener("touchstart", this.touchStart);
      this.$refs.blockPuzzleRef.addEventListener("touchstart", this.touchStart);
      this.$refs.dragBlockRef.addEventListener("mousedown", this.touchStart);
      this.$refs.blockPuzzleRef.addEventListener("mousedown", this.touchStart);
    },
    unbindEvent() {
      this.$refs.dragBlockRef.removeEventListener("touchstart", this.touchStart);
      this.$refs.blockPuzzleRef.removeEventListener("touchstart", this.touchStart);
      window.removeEventListener("touchmove", this.touchMove);
      window.removeEventListener("touchend", this.touchEnd);
      this.$refs.dragBlockRef.removeEventListener("mousedown", this.touchStart);
      this.$refs.blockPuzzleRef.removeEventListener("mousedown", this.touchStart);
      window.removeEventListener("mousemove", this.touchMove);
      window.removeEventListener("mouseup", this.touchEnd);
    }
  },
  created() {
    this.getAppId();
    this.refresh();
  }
};
</script>



<style lang="less" scoped>
.drag-verify-container {
  box-sizing: border-box;
  padding-top: 1.07rem;
  height: 100vh;
  background: white;
  .title,
  .tips {
    text-align: center;
    font-family: Microsoft YaHei;
    font-weight: 400;
  }
  .title {
    font-size: 0.36rem;
    color: #222222;
  }
  .tips {
    margin: 1.32rem 0 0.37rem 0;
    font-size: 0.3rem;
    color: #666666;
  }

  .pic-container {
    position: relative;
    width: fit-content;
    margin: 0 auto;
    img {
      vertical-align: middle;
    }
    .bg {
      //-webkit-user-drag: none;
    }
    .blockPuzzle {
      position: absolute;
      top: 0;
      left: 0;
    }
    .refresh {
      width: 0.53rem;
      height: 0.53rem;
      position: absolute;
      top: 0.12rem;
      right: 0.16rem;
      //-webkit-user-drag: none;
    }
  }
  .drag-block-container {
    position: relative;
    box-sizing: border-box;
    margin: 0.53rem auto 0;
    width: calc(263px + 0.7rem);
    height: 0.66rem;
    border: 1px solid #13cbb9;
    border-radius: 0.04rem;

    font-size: 0.28rem;
    color: #999999;
    text-align: center;
    line-height: 0.67rem;
    overflow: hidden;
    .drag-block-tips {
      position: absolute;

      width: 100%;
      height: 100%;
      text-align: center;
      user-select: none;
      .init-tips {
        height: 100%;
      }
      .success-status {
        display: flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(19, 203, 185, 0.1);
        img {
          margin-right: 0.22rem;
          width: 0.34rem;
          height: 0.23rem;
          vertical-align: middle;
        }
        & > span {
          height: 100%;
        }
      }
    }
    .drag-block {
      position: absolute;
      top: 0;
      left: 0;
      width: 0.7rem;
      height: 100%;
      background-image: url("../../image/drag-verify/drag-clock-1@2x.png");
      background-repeat: no-repeat;
      background-size: 100% 100%;
    }
  }
}
</style>